
#pragma once

#include  <SDL.h>
#include "../Core/Draw.h"
#include "../System/IKeyBoardEventHandler.h"
#include "../System/IMouseEventHandler.h"

namespace Eyas3D
{
	namespace Engine
	{
		//class	EInputListener;
		//class	ECanvas;
		/* 游戏窗口管理类 */
		class Window
		{
		private:
			
		public:
			static int SCREEN_WIDTH = 640;
			static int SCREEN_HEIGHT = 480;
			static bool mQuite;
			/* 全局类指针, 用于在WinProc中回调 */
			static EGameWindow *GWindow;
			static SDL_TimerID mTimer;
			/* window事件处理 */
			//哪些必须对接的节点.消息handle
			void startLoop(){
				SDL_Event myEvent;//事件
				int x,y;	short delta;
				//int quit = 0;
				while ( !mQuite ) //建立事件主循环
				{
					if ( SDL_PollEvent ( &myEvent ) ) //从队列里取出事件
					{
						//获得事件
						switch ( myEvent.type ) //根据事件类型分门别类去处理
						{				
						case SDL_KEYUP:
							switch( myEvent.key.keysym.sym )
							{
								case SDLK_LEFT:
									break;
								case SDLK_RIGHT:
									break;
								case SDLK_UP:
									break;
								case SDLK_SPACE:
									break;
								default:
									break;
							}
							//cout<<myEvent.key.keysym.sym<<endl;
							//printf( "keyup: %d\n", myEvent.key.keysym.sym );
							EGameWindow::GWindow->onKeyRelease( myEvent.key.keysym.sym );
							break;
						case SDL_KEYDOWN:
							//printf( "keydown: %d\n", myEvent.key.keysym.sym );
							EGameWindow::GWindow->onKeyDown( myEvent.key.keysym.sym );
							break;
						case SDL_MOUSEMOTION:
							x	= ( myEvent.motion.x );
							y	= ( myEvent.motion.y );
							EGameWindow::GWindow->onMouseMove( x, y );
							break;
						case SDL_MOUSEWHEEL:
							delta = (short)myEvent.motion.y; /* wheel rotation */
							EGameWindow::GWindow->onMouseWheel( delta * 0.5f / PI );
							break;
						case SDL_MOUSEBUTTONDOWN:
							break;
						case SDL_MOUSEBUTTONUP:
							break;
						case SDL_QUIT://如果是离开事件
							mQuite = true;
							break;
						case SDL_WINDOWEVENT:
							switch (myEvent.window.event) {
							case SDL_WINDOWEVENT_SHOWN:
								SDL_Log("Window %d shown", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_HIDDEN:
								SDL_Log("Window %d hidden", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_EXPOSED:
								EGameWindow::GWindow->onPaint( 0 );
								SDL_Log("Window %d exposed", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_MOVED:
								SDL_Log("Window %d moved to %d,%d",
										myEvent.window.windowID, myEvent.window.data1,
										myEvent.window.data2);
								break;
							case SDL_WINDOWEVENT_RESIZED:
								SDL_Log("Window %d resized to %dx%d",
										myEvent.window.windowID, myEvent.window.data1,
										myEvent.window.data2);
								break;
							case SDL_WINDOWEVENT_SIZE_CHANGED:
								SDL_Log("Window %d size changed to %dx%d",
										myEvent.window.windowID, myEvent.window.data1,
										myEvent.window.data2);
								break;
							case SDL_WINDOWEVENT_MINIMIZED:
								SDL_Log("Window %d minimized", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_MAXIMIZED:
								SDL_Log("Window %d maximized", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_RESTORED:
								SDL_Log("Window %d restored", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_ENTER:
								SDL_Log("Mouse entered window %d",
										myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_LEAVE:
								SDL_Log("Mouse left window %d", myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_FOCUS_GAINED:
								SDL_Log("Window %d gained keyboard focus",
										myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_FOCUS_LOST:
								SDL_Log("Window %d lost keyboard focus",
										myEvent.window.windowID);
								break;
							case SDL_WINDOWEVENT_CLOSE:
								mQuite = true;						
								SDL_Log("Window %d closed", myEvent.window.windowID);
								break;
							default:
								SDL_Log("Window %d got unknown event %d",
										myEvent.window.windowID, myEvent.window.event);
								break;
							}
							//cout<<"SDL_WINDOWEVENT"<<endl;
							break;
						default: // Report an unhandled event, 512, 1025, 1026
							//printf("I don't know what this event is!\n");
							//cout<<myEvent.type<<endl;
							//printf( "unknown event: %d\n", myEvent.type );
							break;
						}
						onUpdate();
					}else{
						//没获得事件
						//::SDL_Delay( 100 );
					}		
					//render
					//一帧一帧渲染
					//撤掉game层
					render();	
				}
				SDL_DestroyWindow ( mHwnd );
				SDL_Quit();
			}
			Window( const String &windowTitle ){
				this->title = windowTitle;
				createWindow();
			}
			~Window(){
				//如果window还存在,就销毁
				if( m_window!=0 )
					destroyWindow();
			}
			void destroyWindow(){
				SDL_DestroyWindow( m_window );
				m_window = 0;
			}
			/* 显示窗口 */
			void showWindow( bool show ){
				//SDL_RaiseWindow
				if( show )
					SDL_ShowWindow( m_window );
				else
					SDL_HideWindow( m_window );
			}
			void updateWindow();
			void quiteApplication(){
				mQuite = true;
			}
			SDL_Window* getHandle() const
			{
				return(m_window);
			}
			/* 注册/移除IO事件监听 */
			void addInputListener( EInputListener* listener );
			void removeInputListener( EInputListener* listener );
			/* 设置绘制监听器, 同时只能有一个绘制Canvas */
			void setCanvasListener( ECanvas *canvasListener );
	protected:
			/* 全局Win事件回调函数 */
			//static long WinProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
			/* 窗口绘制函数 */
			virtual void onPaint( SDL_Window* window );
			virtual void onUpdate();
			virtual void onKeyDown( int msg );
			virtual void onKeyRelease( int msg );
			virtual void onMousePress( bool rightPress );
			virtual void onMouseMove( int x, int y );
			virtual void onMouseWheel( int delta );
	protected:
			/* 注册窗口 */
			bool registerWindow();
			/* 创建窗口 */
			void createWindow(){
				//不将ExitProcess绑定在这个函数里
				//致命错误,就该绑定好
				m_window = SDL_CreateWindow( title,
					SDL_WINDOWPOS_UNDEFINED,           // initial x position
					SDL_WINDOWPOS_UNDEFINED,           // initial y position
					SCREEN_WIDTH, SCREEN_HEIGHT,
					SDL_WINDOW_OPENGL	);
				if ( !m_window )
				{
					SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_INFORMATION, "Create Window Failed, quit now!", 0, 0 );
					SDL_Quit();
				}
			}
			void render();
		protected:
		//protected谁能访问?
			SDL_Window* m_window;
			String				title;
			Eyas3D::Core::Draw *draw;
			//std::vector<EInputListener*>	mInputListeners;
			//ECanvas				*mCanvasListener;
			//typedef std::vector<EInputListener*>::iterator InputItr;
		};
		/*
		 * window framework
		 * createwindow
		 * event_loop{
		 * 	on_mouse:
		 * 	on_keyboard:
		 * 	on_other:
		 * 	render();
		 * }
		 */
		 static void onMouse(){
		 }
		 static void demo1(){
			 //建立窗口
			 //Window window( "test" );
			 SDL_Init(SDL_INIT_VIDEO);
			 SDL_Window* Window = SDL_CreateWindow("SDL_Window", 
						SDL_WINDOWPOS_CENTERED, 
						SDL_WINDOWPOS_CENTERED, 240, 400, 
						SDL_WINDOW_SHOWN|SDL_WINDOW_BORDERLESS ); 
			 //SDL_MapRGB(WindowScreen->format, 0x00, 0xFF, 0x00);
			 SDL_Event myEvent;//事件
			int x,y;	short delta;
			//int quit = 0;
			while ( SDL_PollEvent ( &myEvent ) ) //从队列里取出事件
			{
				//获得事件
				switch ( myEvent.type ) //根据事件类型分门别类去处理
				{
					 case SDL_QUIT: 
						SDL_Quit();
					case SDL_KEYUP:
					switch( myEvent.key.keysym.sym )
					{
						case SDLK_LEFT:
							break;
						case SDLK_RIGHT:
							break;
						case SDLK_UP:
							break;
						case SDLK_SPACE:
							break;
						default:
							break;
					}
					case SDL_WINDOWEVENT:
					switch (myEvent.window.event) {
						case SDL_WINDOWEVENT_SHOWN:
							SDL_Log("Window %d shown", myEvent.window.windowID);
							break;
					}
				}
			}
		 }
		 static void demo2(){
			 
		 }
	}
}
